* Fix compatibility for track filter GUI<->CLI.
Add a week unit for the track filter move option,
in addition to the existing day, hour, minute and second units.
Allow combination of units for track filter move option, e.g.
1w2d3h4m-5s = 1 week + 2 days + 3 hours + 4 minutes - 5 seconds.
This matches historical use, and is expected by the GUI.
Add the week unit to the GUI track filter ui.
Change the limits on the track filter move specs:
week: +/-10000 (unit didn't exit before)
day,hour,minute,second: +/- 100000 (+/-2000 for day before, +/-100 on others).
This resolves #357.
This resolves #358.
* add documentation for track filter move option.
s += QString(",stop=%1").arg(optionDate(stopTime, TZ));
}
if (move) {
- s += QString(",move=%1d%2h%3m%4s").arg(days).arg(hours).arg(mins).arg(secs);
+ s += QString(",move=%1w%2d%3h%4m%5s").arg(weeks).arg(days).arg(hours).arg(mins).arg(secs);
}
if (title) {
s += QString(",title=%1").arg(titleString);
{
public:
TrackFilterData(): FilterData(), title(false), titleString(QString()),
- move(false), days(0), hours(0), mins(0), secs(0),
+ move(false), weeks(0), days(0), hours(0), mins(0), secs(0),
TZ(false),
start(false),
stop(false),
sg.addVarSetting(new DateTimeSetting("trks.stopTime", stopTime));
sg.addVarSetting(new BoolSetting("trks.TZ", TZ));
sg.addVarSetting(new BoolSetting("trks.move", move));
+ sg.addVarSetting(new IntSetting("trks.weeks", weeks));
sg.addVarSetting(new IntSetting("trks.days", days));
sg.addVarSetting(new IntSetting("trks.mins", mins));
sg.addVarSetting(new IntSetting("trks.hours", hours));
bool title;
QString titleString;
bool move;
- int days, hours, mins, secs;
+ int weeks, days, hours, mins, secs;
bool TZ;
bool start;
addCheckEnabler(ui.titleCheck, ui.titleText);
addCheckEnabler(ui.moveCheck,
(QList<QWidget*> ()
+ << ui.weeksLabel << ui.weeksSpin
<< ui.daysLabel << ui.daysSpin
<< ui.hoursLabel<< ui.hoursSpin
<< ui.minsLabel << ui.minsSpin
fopts << new BoolFilterOption(tfd.course, ui.courseCheck);
fopts << new BoolFilterOption(tfd.speed, ui.speedCheck);
- fopts << new IntSpinFilterOption(tfd.days, ui.daysSpin, -2000, 2000);
- fopts << new IntSpinFilterOption(tfd.hours, ui.hoursSpin);
- fopts << new IntSpinFilterOption(tfd.mins, ui.minsSpin);
- fopts << new IntSpinFilterOption(tfd.secs, ui.secsSpin);
+ fopts << new IntSpinFilterOption(tfd.weeks, ui.weeksSpin, ui.weeksSpin->minimum(), ui.weeksSpin->maximum());
+ fopts << new IntSpinFilterOption(tfd.days, ui.daysSpin, ui.daysSpin->minimum(), ui.daysSpin->maximum());
+ fopts << new IntSpinFilterOption(tfd.hours, ui.hoursSpin, ui.hoursSpin->minimum(), ui.hoursSpin->maximum());
+ fopts << new IntSpinFilterOption(tfd.mins, ui.minsSpin, ui.minsSpin->minimum(), ui.minsSpin->maximum());
+ fopts << new IntSpinFilterOption(tfd.secs, ui.secsSpin, ui.secsSpin->minimum(), ui.secsSpin->maximum());
fopts << new IntSpinFilterOption(tfd.splitTime, ui.splitTimeSpin, 0, 1000);
fopts << new IntSpinFilterOption(tfd.splitDist, ui.splitDistSpin, 0, 5280);
<x>0</x>
<y>0</y>
<width>663</width>
- <height>248</height>
+ <height>270</height>
</rect>
</property>
<property name="windowTitle">
</widget>
</item>
<item row="2" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
+ <item>
+ <widget class="QSpinBox" name="weeksSpin">
+ <property name="accelerated">
+ <bool>true</bool>
+ </property>
+ <property name="minimum">
+ <number>-10000</number>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="weeksLabel">
+ <property name="text">
+ <string>weeks</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
- <widget class="QSpinBox" name="daysSpin"/>
+ <widget class="QSpinBox" name="daysSpin">
+ <property name="accelerated">
+ <bool>true</bool>
+ </property>
+ <property name="minimum">
+ <number>-100000</number>
+ </property>
+ <property name="maximum">
+ <number>100000</number>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="daysLabel">
<item row="2" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
- <widget class="QSpinBox" name="hoursSpin"/>
+ <widget class="QSpinBox" name="hoursSpin">
+ <property name="accelerated">
+ <bool>true</bool>
+ </property>
+ <property name="minimum">
+ <number>-100000</number>
+ </property>
+ <property name="maximum">
+ <number>100000</number>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="hoursLabel">
<item row="2" column="4">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
- <widget class="QSpinBox" name="minsSpin"/>
+ <widget class="QSpinBox" name="minsSpin">
+ <property name="accelerated">
+ <bool>true</bool>
+ </property>
+ <property name="minimum">
+ <number>-100000</number>
+ </property>
+ <property name="maximum">
+ <number>100000</number>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="minsLabel">
<item row="2" column="5">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QSpinBox" name="secsSpin"/>
+ <widget class="QSpinBox" name="secsSpin">
+ <property name="accelerated">
+ <bool>true</bool>
+ </property>
+ <property name="minimum">
+ <number>-100000</number>
+ </property>
+ <property name="maximum">
+ <number>100000</number>
+ </property>
+ </widget>
</item>
<item>
<widget class="QLabel" name="secsLabel">
qint64 TrackFilter::trackfilter_parse_time_opt(const char* arg)
{
- qint64 result;
+ qint64 result = 0;
- QRegularExpression re("^([+-]?\\d+)([dhms])$", QRegularExpression::CaseInsensitiveOption);
+ QRegularExpression re("^([+-]?\\d+)([wdhms])(?:([+-]?\\d+)([wdhms]))?(?:([+-]?\\d+)([wdhms]))?(?:([+-]?\\d+)([wdhms]))?(?:([+-]?\\d+)([wdhms]))?$", QRegularExpression::CaseInsensitiveOption);
assert(re.isValid());
QRegularExpressionMatch match = re.match(arg);
if (match.hasMatch()) {
- bool ok;
- result = match.captured(1).toLong(&ok);
- if (!ok) {
- fatal(MYNAME "-time: invalid quantity in move option \"%s\"!\n", qPrintable(match.captured(1)));
- }
+ int lastindex = match.lastCapturedIndex();
+ for (int idx = 1; idx < lastindex; idx += 2) {
+ bool ok;
+ qint64 partial = match.captured(idx).toLong(&ok);
+ if (!ok) {
+ fatal(MYNAME "-time: invalid quantity in move option \"%s\"!\n", qPrintable(match.captured(idx)));
+ }
- switch (match.captured(2).at(0).toLower().toLatin1()) {
- case 'd':
- result *= SECONDS_PER_DAY;
- break;
- case 'h':
- result *= SECONDS_PER_HOUR;
- break;
- case 'm':
- result *= 60;
- break;
- case 's':
- break;
- default:
- fatal(MYNAME "-time: invalid unit in move option \"%s\"!\n", qPrintable(match.captured(2)));
- }
+ switch (match.captured(idx+1).at(0).toLower().toLatin1()) {
+ case 'w':
+ partial *= SECONDS_PER_DAY * 7;
+ break;
+ case 'd':
+ partial *= SECONDS_PER_DAY;
+ break;
+ case 'h':
+ partial *= SECONDS_PER_HOUR;
+ break;
+ case 'm':
+ partial *= 60;
+ break;
+ case 's':
+ break;
+ default:
+ fatal(MYNAME "-time: invalid unit in move option \"%s\"!\n", qPrintable(match.captured(idx+1)));
+ }
+ result += partial;
+
+ }
#ifdef TRACKF_DBG
qDebug() << MYNAME "-time option: shift =" << result << "seconds";
#endif
This option changes the time of all trackpoints. This might be useful if
your track must be moved by one or more hours because of an incorrect
time zone.
+It can also be useful to correct tracks for week number roll over problems.
+</para>
+<para>
+The value of this option is a series of integer and unit pairs. Each integer may include a
+leading '+' or '-' sign. Positive integers shift the tracks later, while negative integers shift
+the tracks earlier. If no sign is provided the integer is assumed to be nonnegative.
+Possible units are w for weeks, d for days, h for hours, m for minutes and s for seconds.
</para>
<example id="ex_track_move">
<title>Time-shifting a track with the track filter</title>
</para>
<para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=+1h -o gpx -F out.gpx</userinput></para>
</example>
+<example id="ex_track_move_wnro">
+<title>Time-shifting a track with the track filter to correct WNRO</title>
+<para>
+The following command line will shift all tracks to be 1024 weeks later. Because the GPS Week Number
+is transmitted modulo 1024 there is the possibility that the recovered timestamp will be off by
+a multiple of 1024 weeks.
+</para>
+<para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=+1024w -o gpx -F out.gpx</userinput></para>
+</example>
+<example id="ex_track_move_combo">
+<title>Time-shifting a track with the track filter with combined units</title>
+<para>
+The following command lines will each shift all tracks to be 1 hour and 1 minute earlier, i.e. 61 minutes earlier.
+</para>
+<para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=-1h-1m -o gpx -F out.gpx</userinput></para>
+<para><userinput>gpsbabel -t -i gpx -f in.gpx -x track,move=-61m -o gpx -F out.gpx</userinput></para>
+</example>